package edu.jhu.secondhome.servlet;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import edu.jhu.secondhome.database.accessors.UserAccessor;
import edu.jhu.secondhome.database.beans.User;

public class ManageAccountServlet extends HttpServlet
{
  /**
   * 
   */
  private static final long serialVersionUID = 7498989444990339769L;

  public void init() throws ServletException
  {
  }

  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException
  {
    processRequest(req, resp);
  }

  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException
  {
    processRequest(req, resp);
  }

  public void processRequest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException
  {
    response.setContentType("text/html;charset=UTF-8");
    ServletContext servletContext = getServletContext();
    HttpSession session = request.getSession();
    
    ArrayList<String> errors = new ArrayList<String>();
    request.setAttribute("errors", errors);
    
    User user;
    Object userObj = session.getAttribute( "user" );
    if ( userObj instanceof User )
      user = (User)userObj;
    else
    {
      errors.add("You must be logged in to manage account information.");

      RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/index.jsp");
      dispatcher.forward(request, response);
      return;
    }
    
    String email = request.getParameter( "reg_email" );
    String email2 = request.getParameter( "reg_email2" );
    String firstName = request.getParameter( "reg_firstName" );
    String lastName = request.getParameter( "reg_lastName" );
    String phoneNum = request.getParameter( "reg_phoneNumber" );
    String address1 = request.getParameter( "reg_address1" );
    String address2 = request.getParameter( "reg_address2" );
    String address3 = request.getParameter( "reg_address3" );
    String city = request.getParameter( "reg_city" );
    String state = request.getParameter( "reg_state" );
    String zip = request.getParameter( "reg_zip" );

    
    if ( email.equals("") )
      errors.add( "E-mail is a required field." );
    if ( email2.equals("") )
      errors.add( "You must repeat your e-mail." );
    if ( firstName.equals("") )
      errors.add( "First Name is a required field." );
    if ( lastName.equals("") )
      errors.add( "Last Name is a required field." );
    if ( phoneNum.equals("") )
      errors.add( "Phone number is a required field." );
    // address2 and address3 are optional
    if ( address1.equals("") )
      errors.add( "Address is a required field." );
    if ( city.equals("") )
      errors.add( "City is a required field." );
    if ( state.equals("") )
      errors.add( "State is a required field." );
    if ( zip.equals("") )
      errors.add( "Zip Code is a required field." );

    // return with the basic form errors
    if ( errors.size() > 0 )
    {
    	loadManageAccount(request, response, servletContext, user);
        return;
    }
    
    if ( !email.equals( email2 ) )
      errors.add( "Your e-mail values must match." );
     
    // return with the mismatched email error
    if ( errors.size() > 0 )
    {
    	loadManageAccount(request, response, servletContext, user);
        return;
    }
    
    try
    {
      UserAccessor userDb = new UserAccessor();

      // Return error if user exists
      if ( !user.getEmail().equals( email ) && userDb.getUserByEmail( email ) != null )
      {
        errors.add( "There is already a user registered to that e-mail address." );
        loadManageAccount(request, response, servletContext, user);
        return;
      }
      
      String fullAddress = User.createAddressString( address1, address2, address3, city, state, zip );
      
      user.setEmail( email );
      user.setFirstName( firstName );
      user.setLastName( lastName );
      
      User toUpdate = userDb.getUserByEmail(user.getEmail());
      toUpdate.setFirstName( firstName );
      toUpdate.setLastName( lastName );
      toUpdate.setPhoneNumber( phoneNum );
      toUpdate.setCurrentAddress( fullAddress );
      
      userDb.updateUser( toUpdate );
      
    } catch (SQLException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
      errors.add(e.getMessage());
    }
    
    if ( errors.size() > 0 )
    {
    	loadManageAccount(request, response, servletContext, user);
        return;
    }
    else
    {
      request.setAttribute( "message", "Successfully updated account information." );
      loadManageAccount(request, response, servletContext, user);
      return;
    }
  }
  
  private void loadManageAccount( HttpServletRequest request,
      HttpServletResponse response, ServletContext servletContext,
      final User user ) throws ServletException, IOException
  {
    UserAccessor ua = new UserAccessor();
    loadAndStoreDatabaseUser( request, response, servletContext, user, ua );
    
    if ( user.isAdmin() )
    {
      List<String> admins;
      try
      {
        admins = ua.getUserEmailsAdminStatus( true );
      } catch ( SQLException e )
      {
        log( "Couldn't retrieve admin users for account management.", e );
        admins = Collections.emptyList();
      }
      List<String> users;
      try
      {
        users = ua.getUserEmailsAdminStatus( false );
      } catch ( SQLException e )
      {
        log( "Couldn't retrieve non-admin users for account management.", e );
        users = Collections.emptyList();
      }

      if ( admins == null )
        admins = Collections.emptyList();
      if ( users == null )
        users = Collections.emptyList();
      request.setAttribute( "admins", admins );
      request.setAttribute( "users", users );
    }
    // Forward the request to manageAccount.jsp
    RequestDispatcher dispatcher = servletContext
        .getRequestDispatcher( "/manageAccount.jsp" );
    dispatcher.forward( request, response );
  }
  
  protected void loadAndStoreDatabaseUser( HttpServletRequest request,
      HttpServletResponse response, ServletContext servletContext, User user,
      UserAccessor ua )
  {
    User dbUser;
    try
    {
      dbUser = ua.getUserByEmail( user.getEmail() );
    } catch ( SQLException e )
    {
      // this should never happen since it's the currently logged in user.
      log( "Couldn't retrieve user data for email " + user.getEmail(), e );
      dbUser = user;
    }
    String cardNum = dbUser.getCreditCardNum();
    dbUser.setPassword( "" );
    dbUser.setCreditCardSecCode( "" );
    if ( cardNum != null && !cardNum.isEmpty() )
    {
      final int length = cardNum.length();
      if ( length > 4 )
      {
        dbUser.setCreditCardNum( cardNum.substring( 0, ( length - 4 ) )
            .replaceAll( "\\d", "*" ) + cardNum.substring( length - 4 ) );
      }
    }
    request.setAttribute( "dbUser", dbUser );   
  }
}
